package in.muton.edushare.grading.panels.prevgrades;

import in.muton.edushare.grading.panels.studentGrades.GradingUtil;
import in.muton.edushare.grading.panels.studentGrades.GradingUtil.CourseGradeHelper;
import in.muton.edushare.pages.EduShareBasePage;
import in.muton.edushare.pages.common.EdusharePanel;
import in.muton.edushare.pages.cp.PrevCourseGradesXLS;
import in.muton.edushare.wicket.models.CayenneModel;

import java.util.ArrayList;
import java.util.List;

import org.apache.wicket.markup.html.WebMarkupContainer;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.list.ListItem;
import org.apache.wicket.markup.html.list.ListView;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

import com.edushare.common.dao.BatchDAO;
import com.edushare.common.dao.CourseInstancesDAO;
import com.edushare.common.dao.CoursesDAO;
import com.edushare.common.dao.EnrolmentsDAO;
import com.edushare.common.dao.UserRolesDAO;
import com.edushare.common.dao.academics.history.BatchEnrol;
import com.edushare.common.util.StringUtil;
import com.edushare.common.vo.AcademicYearModel;
import com.edushare.common.vo.Batches;
import com.edushare.common.vo.CourseInstances;
import com.edushare.common.vo.Courses;
import com.edushare.common.vo.FilesUploaded;
import com.edushare.common.vo.Universities;
import com.edushare.common.vo.Users;

public class PrevCourseGradeConfirm extends EdusharePanel {
	private ExcelSheetDisplayPanel confirmPanel;
	private IModel<Universities> univModel;
	private IModel<AcademicYearModel> semester;
	private int acadYear;
	private List<String> statusString = new ArrayList<String>();
	private int userCount = 0;
	private int gradeCount = 0;
	private boolean wmcVisibility = false;

	public PrevCourseGradeConfirm(String id, final IModel<Universities> model,
			IModel<FilesUploaded> fileUploadedModel, int acadYear,
			IModel<AcademicYearModel> semester, EduShareBasePage page) {
		super(id, model, page);
		this.acadYear = acadYear;
		this.semester = semester;
		this.univModel = model;
		WebMarkupContainer wmc = new WebMarkupContainer("WMC") {
			private static final long serialVersionUID = 4940271404181259042L;

			@Override
			public boolean isVisible() {
				return wmcVisibility;
			}
		};
		add(wmc);
		wmc.add(new Label("summary", new Model<String>() {
			private static final long serialVersionUID = 4966785789844891792L;

			@Override
			public String getObject() {
				return "Added " + gradeCount + " grades for " + userCount
						+ " users.";
			}
		}));
		wmc.add(new ListView<String>("errorLV", new IModel<List<String>>() {
			private static final long serialVersionUID = 1L;

			public List<String> getObject() {
				return statusString;
			}

			public void setObject(List<String> arg0) {
			}

			public void detach() {
			}
		}) {
			private static final long serialVersionUID = 515185611375966887L;

			@Override
			protected void populateItem(ListItem<String> arg0) {
				arg0.add(new Label("error", arg0.getModelObject()));
			}
		});

		add(confirmPanel = new ExcelSheetDisplayPanel("excelDataView",
				fileUploadedModel, page) {
			private static final long serialVersionUID = 2197784185109047558L;

			@Override
			public void onCancel() {
				setResponsePage(new PrevCourseGradesXLS(model));
			}

			@Override
			public void onSubmit() {
				wmcVisibility = true;
				uploadData();
			}

			@Override
			public boolean isVisible() {
				return !wmcVisibility;
			}
		});
	}

	private void uploadData() {
		List<String[]> fields = confirmPanel.getFields();
		String[] row1 = fields.get(0);
		UserRolesDAO urDAO = new UserRolesDAO(getORMInterface());

		for (int userRow = 1; userRow < fields.size(); userRow++) {
			String[] row = fields.get(userRow);
			String userID = row[0];
			Users u = urDAO.getUserByUniqueId(userID);
			if (u == null) {
				statusString.add("Could not find user " + userID);
				continue;
			}
			userCount++;
			for (int courseCol = 1; courseCol < row1.length; courseCol++) {
				CourseInstances cInst = getInst(row1[courseCol]);
				if (cInst == null) {
					statusString.add("Unable to find course with code "
							+ row1[courseCol]);
					continue;
				}
				String grade = fields.get(userRow)[courseCol];
				if(!StringUtil.isValid(grade))
					continue;
				enrolPerson(cInst, u);
				if (!updateGrade(cInst, u, grade)) {
					statusString.add("Unable to add grade" + grade
							+ " for user " + u.getCompleteUserName()
							+ " and course " + cInst.getName());
				} else {
					gradeCount++;
				}
			}
			List<Batches> batchList = new BatchDAO(getORMInterface())
					.getUserBatches(u);
			for (Batches b : batchList) {
				new BatchEnrol(getORMInterface()).userUpdateTasks(u, b);
			}
		}
	}

	private void enrolPerson(CourseInstances cInst, Users student) {
		new EnrolmentsDAO(getORMInterface()).enrolStudent(cInst, student);
	}

	private CourseInstances getInst(String courseId) {
		CoursesDAO courseDAO = new CoursesDAO(getORMInterface());
		CourseInstancesDAO cInstDAO = new CourseInstancesDAO(getORMInterface());
		Courses course = courseDAO.getCourseByID(univModel.getObject(),
				courseId);
		if (course == null)
			return null;
		CourseInstances cinst = cInstDAO.getInstanceByYearAndSem(course,
				acadYear, semester.getObject());
		if (cinst == null) {
			cinst = cInstDAO.createInstanceByYearAndSem(course, acadYear,
					semester.getObject());
		}
		return cinst;
	}

	private boolean updateGrade(CourseInstances cInst, Users user, String grade) {
		GradingUtil util = new GradingUtil(new CayenneModel<CourseInstances>(
				cInst));
		if (!StringUtil.isValid(grade)) {
			return false;
		}
		CourseGradeHelper cgh = util.getGrades(user);
		cgh.temp = grade;
		if (cgh.isLetterGrade && !util.isValidKey(grade)) {
			return false;
		}
		if (!cgh.isLetterGrade) {
			try {
				cgh.marks = Double.parseDouble(cgh.temp);
			} catch (NumberFormatException e) {
				return false;
			}
		}
		util.saveMarks(cgh);
		return true;
	}

	private static final long serialVersionUID = 5310020045380066185L;
}
